#ifndef _TELLENC_PRIV_H_
#define _TELLENC_PRIV_H_ 1

#include "tree.h"				/* BSD red-black tree */
#include "tellenc.h"			/* for enum tellenc_enc */

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr)			(sizeof(arr) / sizeof((arr)[0]))
#endif

#define TELLENC_BYTE_MAX		256
#define TELLENC_BUFFER_SIZE		(1024 * 200)
#define TELLENC_NUL				'\0'
#define TELLENC_DOS_EOF			'\x1a'
#define TELLENC_EVEN			0
#define TELLENC_ODD				1

#define TELLENC_CHAR_IS_NON_TEXT(c)	\
		( (c) == 0 || (c) == 26 || (c) == 127 )

enum tellenc_utf8_state {
	TELLENC_UTF8_INVAL,
	TELLENC_UTF8_1,
	TELLENC_UTF8_2,
	TELLENC_UTF8_3,
	TELLENC_UTF8_4,
	TELLENC_UTF8_TAIL
};

/*
 * RATIONALE: The codepoint fields  of the following structs (tebc_code &
 * tedc_code) uses `int' rather than `uint32_t', because UCS-4 demands that its
 * MSB must be 0.  BTW, UCS-4 currently only defines BMP characters, i.e.,
 * UCS-4 has no characters with non-zero high 16 bit value. (BMP: basic
 * multi-lingual plane, for the 4-byte sequence, the first two bytes are zero)
 */

/* single byte characters (ASCII) count struct */
struct tellenc_byte_count {
	int							tebc_code;
	int							tebc_count;
};

/* double-byte characters count struct */
struct tellenc_dbyte_count {
	int							tedc_code;
	int							tedc_count;
	RB_ENTRY(tellenc_dbyte_count) tedc_node;
};

struct tellenc_data_map {
	int							tem_code;
	enum tellenc_enc			tem_enc;
};

/* Red-black tree type: struct tellenc_dbc_tree */
RB_HEAD(tellenc_dbc_tree, tellenc_dbyte_count);

#define TELLENC_F_BINARY		0x1
#define TELLENC_F_NON_UTF8		0x2
#define TELLENC_F_NON_LATIN1	0x4
#define TELLENC_F_UCSBOM		0x8
#define TELLENC_F_EMPTY			0x10

struct tellenc_ctx {
	const unsigned char			*te_buf;
	int							te_buflen;
	int							te_flags;		/* TELLENC_F_ */
	int							te_nul_byte[2];
	int							te_nul_word[2];
	int							te_dbyte_cnt;	/* Double-byte count (all) */
	int							te_dbuniq_cnt;	/* Double-byte count (unique) */
	int							te_dbhihi_cnt;	/* Double-byte with
												   hi-hi word count */
	int							te_bomlen;		/* Encoding determined */
	enum tellenc_enc			te_bomenc;		/* from UCS BOM */
	struct tellenc_byte_count	te_byte_tbl[TELLENC_BYTE_MAX];
	struct tellenc_dbyte_count	**te_dbyte_tbl;
	struct tellenc_dbc_tree		te_tree;
};

extern const struct tellenc_data_map tellenc_freqmap[TELLENC_BYTE_MAX];

#endif	/* _TELLENC_PRIV_H_ */
